Here is another, it uses a map instead of append. Spot products are produced for products with no number. It is also deterministic.
Multiplier:
amul([], _Other_Row,[]).
amul([X|Xs],Other_Row,[Row_Out|Rest_Out]) :-
maplist(mul(X),Other_Row, Row_Out),
amul(Xs,Other_Row, Rest_Out).
:
mul(X,Y, Prod) :-
( number(X), number(Y)
-> Prod is X * Y
; true
-> Prod = dot(X,Y)
).
[1,3,5] X [2,4,6]
?- amul([1,3,5], [2,4,6],Prod).
Prod = [[2, 4, 6], [6, 12, 18], [10, 20, 30]].
[a, b, c] X [1,2,3,4]
?- amul([a,b,c],[1,2,3,4],Prod).
Prod = [[dot(a, 1), dot(a, 2), dot(a, 3), dot(a, 4)],
[dot(b, 1), dot(b, 2), dot(b, 3), dot(b, 4)],
[dot(c, 1), dot(c, 2), dot(c, 3), dot(c, 4)]].