In [235]: A = np.random.random((10,800))
...: B = np.random.random((10,500))
...: C = np.zeros((800,500,10))
...: for k in range(10):
...: C[:,:,k] = A[k,:][:,None] @ B[k,:][None,:]
...:
In [236]: C.shape
Out[236]: (800, 500, 10)
Пакетное матричное произведение с последующей транспонированием
In [237]: np.allclose((A[:,:,None]@B[:,None,:]).transpose(1,2,0), C)
Out[237]: True
Но так как ось матричного произведения имеет размер 1, и нет другого суммирования, переданное умножение так же хорошо:
In [238]: np.allclose((A[:,:,None]*B[:,None,:]).transpose(1,2,0), C)
Out[238]: True
Время выполнения примерно одинаково