function concat_(tensors, axis = 0) {
    (0, _util.assert)(tensors.length >= 1, ()=>"Pass at least one tensor to concat");
    const $tensors = (0, _tensorUtilEnv.convertToTensorArray)(tensors, "tensors", "concat", "string_or_numeric");
    if ($tensors[0].dtype === "complex64") $tensors.forEach((tensor)=>{
        if (tensor.dtype !== "complex64") throw new Error(`Cannot concatenate complex64 tensors with a tensor
          with dtype ${tensor.dtype}. `);
    });
    if ($tensors.length === 1) return (0, _clone.clone)($tensors[0]);
    const inputs = $tensors;
    const attr = {
        axis
    };
    return (0, _engine.ENGINE).runKernel((0, _kernelNames.Concat), inputs, attr);
}
Concatenates a list of `tf.Tensor`s along a given axis.

The tensors ranks and types must match, and their sizes must match in all
dimensions except `axis`.

Also available are stricter rank-specific methods that assert that
`tensors` are of the given rank:
  - `tf.concat1d`
  - `tf.concat2d`
  - `tf.concat3d`
  - `tf.concat4d`

Except `tf.concat1d` (which does not have axis param), all methods have
same signature as this method.

```js
const a = tf.tensor1d([1, 2]);
const b = tf.tensor1d([3, 4]);
a.concat(b).print();  // or a.concat(b)
```

```js
const a = tf.tensor1d([1, 2]);
const b = tf.tensor1d([3, 4]);
const c = tf.tensor1d([5, 6]);
tf.concat([a, b, c]).print();
```

```js
const a = tf.tensor2d([[1, 2], [10, 20]]);
const b = tf.tensor2d([[3, 4], [30, 40]]);
const axis = 1;
tf.concat([a, b], axis).print();
```
@param tensors A list of tensors to concatenate.
@param axis The axis to concatenate along. Defaults to 0 (the first dim).

@doc {heading: 'Tensors', subheading: 'Slicing and Joining'}