code: def concatenate(arrays, axis=0, always_copy=True):
      
      assert isinstance(arrays, list)
      assert len(arrays) > 0
      assert isinstance(arrays[0], NDArray)
  
      if not always_copy and len(arrays) == 1:
          return arrays[0]
  
      shape_axis = arrays[0].shape[axis]
      shape_rest1 = arrays[0].shape[0:axis]
      shape_rest2 = arrays[0].shape[axis+1:]
      dtype = arrays[0].dtype
      for arr in arrays[1:]:
          shape_axis += arr.shape[axis]
          assert shape_rest1 == arr.shape[0:axis]
          assert shape_rest2 == arr.shape[axis+1:]
          assert dtype == arr.dtype
      ret_shape = shape_rest1 + (shape_axis,) + shape_rest2
      ret = empty(ret_shape, ctx=arrays[0].context, dtype=dtype)
  
      idx = 0
      begin = [0 for _ in ret_shape]
      end = list(ret_shape)
      for arr in arrays:
          if axis == 0:
              ret[idx:idx+arr.shape[0]] = arr
          else:
              begin[axis] = idx
              end[axis] = idx+arr.shape[axis]
              # pylint: disable=no-member,protected-access
              _internal._crop_assign(ret, arr, out=ret,
                                     begin=tuple(begin),
                                     end=tuple(end))
              # pylint: enable=no-member,protected-access
          idx += arr.shape[axis]
  
      return ret
docs: DEPRECATED, use ``concat`` instead
  
      Parameters
      ----------
      arrays : list of `NDArray`
          Arrays to be concatenate. They must have identical shape except
          the first dimension. They also must have the same data type.
      axis : int
          The axis along which to concatenate.
      always_copy : bool
          Default `True`. When not `True`, if the arrays only contain one
          `NDArray`, that element will be returned directly, avoid copying.
  
      Returns
      -------
      NDArray
          An `NDArray` that lives on the same context as `arrays[0].context`.