REF: dont use numexpr in places where it doesnt help.
DataFrame ops will still use it when dispatching to series/block ops.

Perf neutral:

```
In [3]: arr = np.arange(10**4).reshape(100, 100)                                                                                                                                    
In [4]: df = pd.DataFrame(arr)                                                                                                                                                      
In [5]: df[4] = df[4].astype(float)                                                                                                                                                 
In [6]: ser = df[0]                     
                                                                                                                                            
In [8]: %timeit res = df+ser                                                                                                                                                        
19.8 ms ± 317 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <-- PR
19.8 ms ± 267 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <-- master

In [10]: %timeit res2 = df.add(ser, axis=0)                                                                                                                                         
19.2 ms ± 276 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <-- PR
19.2 ms ± 301 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <-- master

In [13]: %timeit res3 = df + df                                                                                                                                                     
23.6 ms ± 382 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <-- PR
24 ms ± 551 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <-- master
```
closing in favor of #32047.