NumPy is the fundamental package for scientific computing with Python. It contains among other things: a powerful N-dimensional array object;

```
import numpy as np
T = np.array([
[[1,2,3], [4,5,6], [7,8,9]],
[[11,12,13], [14,15,16], [17,18,19]],
[[21,22,23], [24,25,26], [27,28,29]],
])
print(T.shape) # (3,3,3)
print(T.ndim) # 3
print(T.size) # 27
print(T)
```

Each array has attributes `ndim`

(the number of dimensions), `shape`

(the size of each dimension), and `size`

(the total size of the array):

When you need to randomly set the tensor with some default values you may use this:

```
import numpy as np
np.random.seed(0) # we used seed to reproduce this again
# x1, x2, x3 are tensors
x1 = np.random.randint(10, size=3) # 1D
x2 = np.random.randint(10, size=(3, 4)) # 2D
x3 = np.random.randint(10, size=(3, 4, 5)) # 3D
```

Operation we can do on tensors is dot product:

```
c = np.tensordot(x1, x2, axes=0)
print(c)
```

For tensor addition and tensor subtraction operations the tensors need to have the same shape. These are element wise operations.

```
import numpy as np
np.random.seed(0)
x21 = np.random.randint(10, size=(3, 4)) # 2D
x22 = np.random.randint(10, size=(3, 4)) # 2D
c = x21 + x22
```

This would not work because the tensors need to be with the same shape

```
x21 = np.random.randint(10, size=(4, 4)) # 2D
x22 = np.random.randint(10, size=(3, 4)) # 2D
c = x21 + x22
```

The following error `ValueError: operands could not be broadcast together with shapes (4,4) (3,4)`

would occure.

The same shape principle need to be also for the element vise multiplication and element vise division.