I'm not saying that Python choices are wrong, I'm just saying that if * is elementwise product, then (A*B)@C <> A*(B@C) should imply to choose different levels fro * and @.

By choosing A*B@C = (A*B)@C, that is a convention, we just say that a human who want to calculate something like A*B@C*D@E@G*H*K will have to start first with the elementwise products and then finish by the matrix product that is to say this human will evaluate (A*B)@(C*D)@E@(G*H*K).

Maybe you should argue to calculate first the @-products but this will not be a good choice if * is the product of a scalar with a matrix like in 2*A@3*B.

1) If A*B@C*D@E@G*H*K = (A*B)@(C*D)@E@(G*H*K), you quickly evaluate first X = A*B, Y = C*D and Z = G*H*K, and then you can do an efficient @-product of X, Y and Z.

2) If you calculate from left to right, you will do three @-products on couple without having the possibility to choose the more efficient way to evaluate the @-products.

Christophe BAL

PS1: // is an approximate calculation of the exact mathematical inversion, so it is not really a counter example.

PS2: here is a second time my example showing that (A*B)@C <> A*(B@C).