def METHOD_NAME(*args):
    """
    Tensor product among scalars or array-like objects.
    Examples
    ========
    >>> A = Array([[1, 2], [3, 4]])
    >>> B = Array([x, y])
    >>> tensorproduct(A, B)
    [[[x, y], [2*x, 2*y]], [[3*x, 3*y], [4*x, 4*y]]]
    >>> tensorproduct(A, x)
    [[x, 2*x], [3*x, 4*x]]
    >>> tensorproduct(A, B, B)
    [[[[x**2, x*y], [x*y, y**2]], [[2*x**2, 2*x*y], [2*x*y, 2*y**2]]],
     [[[3*x**2, 3*x*y], [3*x*y, 3*y**2]], [[4*x**2, 4*x*y], [4*x*y, 4*y**2]]]]
    Applying this function on two matrices will result in a rank 4 array.
    >>> m = Matrix([[x, y], [z, t]])
    >>> p = tensorproduct(eye(3), m)
    >>> p
    [[[[x, y], [z, t]], [[0, 0], [0, 0]], [[0, 0], [0, 0]]],
     [[[0, 0], [0, 0]], [[x, y], [z, t]], [[0, 0], [0, 0]]],
     [[[0, 0], [0, 0]], [[0, 0], [0, 0]], [[x, y], [z, t]]]]
    """
    if len(args) == 0:
        return Integer(1)
    if len(args) == 1:
        return _arrayfy(args[0])
    if len(args) > 2:
        return METHOD_NAME(METHOD_NAME(args[0], args[1]), *args[2:])
    # length of args is 2:
    a, b = map(_arrayfy, args)
    if not isinstance(a, NDimArray) or not isinstance(b, NDimArray):
        return a*b
    al = list(a)
    bl = list(b)
    product_list = [i*j for i in al for j in bl]
    return ImmutableDenseNDimArray(product_list, a.shape + b.shape)