Repository: pytorch
Issue: [typing] Not all operators correctly infer Tensor result.
Labels: module: typing

### 🐛 Describe the bug

<details> <summary> Static Typing Test suite </summary>

```python
# mypy: enable-error-code="unused-ignore"
import operator

import torch
from torch import Tensor
from typing_extensions import assert_type, reveal_type

x = torch.randn(3)
assert_type(x, Tensor)

i64: int = 2
f64: float = 3.14

# op(Tensor, Tensor)
assert_type(x + x, Tensor)
assert_type(x - x, Tensor)
assert_type(x * x, Tensor)
assert_type(x / x, Tensor)
assert_type(x % x, Tensor)
assert_type(x // x, Tensor)  # type: ignore[assert-type]
assert_type(x**x, Tensor)  # type: ignore[assert-type]
# comparisons
assert_type(x < x, Tensor)
assert_type(x > x, Tensor)
assert_type(x <= x, Tensor)
assert_type(x >= x, Tensor)
assert_type(x == x, Tensor)
assert_type(x != x, Tensor)

# op(Tensor, int)
assert_type(x + i64, Tensor)
assert_type(x - i64, Tensor)
assert_type(x * i64, Tensor)
assert_type(x / i64, Tensor)
assert_type(x % i64, Tensor)
assert_type(x // i64, Tensor)  # type: ignore[assert-type]
assert_type(x**i64, Tensor)  # type: ignore[assert-type]
assert_type(x < i64, Tensor)
assert_type(x > i64, Tensor)
assert_type(x <= i64, Tensor)
assert_type(x >= i64, Tensor)
assert_type(x == i64, Tensor)
assert_type(x != i64, Tensor)

# op(Tensor, float)
assert_type(x + f64, Tensor)
assert_type(x - f64, Tensor)
assert_type(x * f64, Tensor)
assert_type(x / f64, Tensor)
assert_type(x % f64, Tensor)
assert_type(x // f64, Tensor)  # type: ignore[assert-type]
assert_type(x**f64, Tensor)  # type: ignore[assert-type]
assert_type(x < f64, Tensor)
assert_type(x > f64, Tensor)
assert_type(x <= f64, Tensor)
assert_type(x >= f64, Tensor)
assert_type(x == f64, Tensor)
assert_type(x != f64, Tensor)

# op(int, Tensor)
assert_type(i64 + x, Tensor)
assert_type(i64 - x, Tensor)  # type: ignore[assert-type]
assert_type(i64 * x, Tensor)
assert_type(i64 / x, Tensor)  # type: ignore[assert-type]
assert_type(i64 % x, Tensor)  # type: ignore[assert-type]
assert_type(i64 // x, Tensor)  # type: ignore[assert-type]
assert_type(i64**x, Tensor)  # type: ignore[assert-type]
assert_type(i64 < x, Tensor)
assert_type(i64 > x, Tensor)
assert_type(i64 <= x, Tensor)
assert_type(i64 >= x, Tensor)
assert_type(i64 == x, Tensor)  # type: ignore[assert-type]
assert_type(i64 != x, Tensor)  # type: ignore[assert-type]

# op(float, Tensor)
assert_type(f64 + x, Tensor)
assert_type(f64 - x, Tensor)  # type: ignore[assert-type]
assert_type(f64 * x, Tensor)
assert_type(f64 / x, Tensor)  # type: ignore[assert-type]
assert_type(f64 % x, Tensor)  # type: ignore[assert-type]
assert_type(f64 // x, Tensor)  # type: ignore[assert-type]
assert_type(f64**x, Tensor)  # type: ignore[assert-type]
assert_type(f64 < x, Tensor)
assert_type(f64 > x, Tensor)
assert_type(f64 <= x, Tensor)
assert_type(f64 >= x, Tensor)
assert_type(f64 == x, Tensor)  # type: ignore[assert-type]
assert_type(f64 != x, Tensor)  # type: ignore[assert-type]


OPS = [
    operator.add,  # +
    operator.sub,  # -
    operator.mul,  # *
    operator.truediv,  # /
    operator.mod,  # %
    operator.floordiv,  # //
    operator.pow,  # **
    operator.le,  # <
    operator.gt,  # >
    operator.lt,  # <=
    operator.ge,  # >=
    operator.eq,  # ==
    operator.ne,  # !=
]

for rhs in [x, i64, f64]:
    for op in OPS:
        assert isinstance(op(x, rhs), Tensor)
for lhs in [x, i64, f64]:
    for op in OPS:
        assert isinstance(op(lhs, x), Tensor)
```

</details>

## Results

Arithmetic, should be fixable by typing `_handle_torch_function_and_wrap_type_error_to_not_implemented` decorator used in `torch/_tensor.py`. 

- [ ] `Tensor // Tensor` inferred as `Any`, not `Tensor`
- [ ] `Tensor ** Tensor` inferred as `Any`, not `Tensor`
- [ ] `Tensor // Number` inferred as `Any`, not `Tensor`
- [ ] `Tensor ** Number` inferred as `Any`, not `Tensor`
- [ ] `Number - Tensor` inferred as `Any`, not `Tensor`
- [ ] `Number / Tensor` inferred as `Any`, not `Tensor`
- [ ] `Number % Tensor` inferred as `Any`, not `Tensor`
- [ ] `Number // Tensor` inferred as `Any`, not `Tensor`
- [ ] `Number ** Tensor` inferred as `Any`, not `Tensor`

Comparisons, possibly unfixable currently

- [ ] `Number == Tensor` inferred as `bool`, not `Tensor`
- [ ] `Number != Tensor` inferred as `bool`, not `Tensor`






### Versions

Tested with both 2.5.1 and 2.7.0.dev20250128+cu124 nightly

cc @ezyang @malfet @xuzhao9 @gramster