For the element-wise HLO operations, we need an `Elementwise`

trait, however, we cannot guarantee the properties that come with `ElementwiseMappable`

as the HLO ops are always on tensors. We would like to split `ElementwiseMappable`

up into three traits `Elementwise`

, `Scalarizable`

, `Vectorizable`

, and `Tensorizable`

to allow for reuse.

`Elementwise`

would guarantee properties 1 - 4:

```
/// 1. If any result is a vector (resp. tensor), then at least one operand must
/// be a vector (resp. tensor).
/// 2. If any operand is a vector (resp. tensor), then there must be at least
/// one result, and all results must be vectors (resp. tensors).
/// 3. The static types of all vector (resp. tensor) operands and results must
/// have the same shape.
/// 4. In the case of tensor operands, the dynamic shapes of all tensor operands
/// must be the same, otherwise the op has undefined behavior.
```

`Scalarizable`

would guarantee property 5:

```
/// 5. ("systematic scalarization" property) If an op has vector/tensor
/// operands/results, then the same op, with the operand/result types changed to
/// their corresponding element type, shall be a verifier-valid op.
```

`Vectorizable`

and `Tensorizable`

would guarantee properties 6 & 7:

```
/// 6. The semantics of the op on vectors (resp. tensors) shall be the same as
/// applying the scalarized version of the op for each corresponding element of
/// the vector (resp. tensor) operands in parallel.
/// 7. ("systematic vectorization/tensorization" property) If an op has
/// scalar operands/results, the op shall remain verifier-valid if all scalar
/// operands are replaced with vectors/tensors of the same shape and
/// corresponding element types.
```