The answer above matches the behavior of np.tensordot
For those looking to do slice multiplication over 3D tensors, torch.matmul might be better.
A = torch.tensor([[[i for i in range(1,3)]] * 5] * 2)
>>>tensor([[[1, 2],
         [1, 2],
         [1, 2],
         [1, 2],
         [1, 2]],

        [[1, 2],
         [1, 2],
         [1, 2],
         [1, 2],
         [1, 2]]])
A.size()
>>>torch.Size([2, 5, 2])

B = torch.tensor([[[i for i in range(2,4)]] * 3] * 2)
>>>tensor([[[2, 3],
         [2, 3],
         [2, 3]],

        [[2, 3],
         [2, 3],
         [2, 3]]])
B.size()
>>>torch.Size([2, 3, 2])

# np.tensordot result:
D = np.tensordot(A.numpy(), B.numpy(), axes=([0, 2], [0, 2]))
>>>array([[16, 16, 16],
       [16, 16, 16],
       [16, 16, 16],
       [16, 16, 16],
       [16, 16, 16]])

## The proposed solution above:
A.transpose(1,2).contiguous().view(2*2,-1).transpose(0,1)
>>>tensor([[1, 2, 1, 2],
        [1, 2, 1, 2],
        [1, 2, 1, 2],
        [1, 2, 1, 2],
        [1, 2, 1, 2]])

B.transpose(1,2).contiguous().view(2*2,-1)
>>>tensor([[2, 2, 2],
        [3, 3, 3],
        [2, 2, 2],
        [3, 3, 3]])

torch.mm(A.transpose(1,2).contiguous().view(2*2,-1).transpose(0,1),
         B.transpose(1,2).contiguous().view(2*2,-1))
>>>tensor([[16, 16, 16],
        [16, 16, 16],
        [16, 16, 16],
        [16, 16, 16],
        [16, 16, 16]])
# --> Equivalent to tensordot answer


# With matmul, we can get slice by slice:
torch.matmul(A,B.transpose(1,2))
>>>tensor([[[8, 8, 8],
         [8, 8, 8],
         [8, 8, 8],
         [8, 8, 8],
         [8, 8, 8]],

        [[8, 8, 8],
         [8, 8, 8],
         [8, 8, 8],
         [8, 8, 8],
         [8, 8, 8]]])