Incorrect invalid device error introduced in #25956

### Describe the bug

#25956 introduced a new `sklearn.utils._array_api._check_device_cpu` function to test whether a tensor is on CPU. However, the implementation of the test, which is `device not in {"cpu", None}`, is incorrect -- the device will actually not be a string, but `device(type='cpu')`. Therefore, you should attempt to get the `type` attr, and use that if available.

### Steps/Code to Reproduce

You can view a sample error here:
https://github.com/fastai/fastai/actions/runs/9232979440/job/25404873935

### Expected Results

`ValueError: Unsupported device for NumPy: device(type='cpu')`  should not be thrown.

### Actual Results

```
File /opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/sklearn/utils/_array_api.py:308, in _check_device_cpu(device)
    306 def _check_device_cpu(device):  # noqa
    307     if device not in {"cpu", None}:
--> 308         raise ValueError(f"Unsupported device for NumPy: {device!r}")

ValueError: Unsupported device for NumPy: device(type='cpu')
```

### Versions

```shell
I've seen this on multiple Linux and Mac versions. My current Mac version:


System:
    python: 3.11.8 (main, Feb 26 2024, 15:36:12) [Clang 14.0.6 ]
executable: /Users/jhoward/miniconda3/bin/python
   machine: macOS-14.3.1-arm64-arm-64bit

Python dependencies:
      sklearn: 1.4.2
          pip: 23.3.1
   setuptools: 68.2.2
        numpy: 1.26.4
        scipy: 1.13.0
       Cython: None
       pandas: 2.2.1
   matplotlib: 3.8.4
       joblib: 1.4.0
threadpoolctl: 2.2.0

Built with OpenMP: True

threadpoolctl info:
       filepath: /Users/jhoward/miniconda3/lib/libopenblasp-r0.3.21.dylib
         prefix: libopenblas
       user_api: blas
   internal_api: openblas
        version: 0.3.21
    num_threads: 8
threading_layer: pthreads
   architecture: armv8

       filepath: /Users/jhoward/miniconda3/lib/libomp.dylib
         prefix: libomp
       user_api: openmp
   internal_api: openmp
        version: None
    num_threads: 8
```
```

COMMENT:
Ok I understand, it's happening when array API dispatch is disabled and regular numpy code is expected:

```python
>>> import numpy as np
>>> import sklearn
>>> sklearn.set_config(array_api_dispatch=False)
>>> from sklearn.metrics import r2_score
>>> import torch
>>> x1, x2 = torch.randn(20, 5), torch.randn(20, 5)
>>> r2_score(x2.view(-1), x1.view(-1))
Traceback (most recent call last):
  Cell In[27], line 7
    r2_score(x2.view(-1), x1.view(-1))
  File ~/code/scikit-learn/sklearn/utils/_param_validation.py:213 in wrapper
    return func(*args, **kwargs)
  File ~/code/scikit-learn/sklearn/metrics/_regression.py:1242 in r2_score
    return _assemble_r2_explained_variance(
  File ~/code/scikit-learn/sklearn/metrics/_regression.py:897 in _assemble_r2_explained_variance
    output_scores = xp.ones([n_outputs], device=device, dtype=dtype)
  File ~/code/scikit-learn/sklearn/utils/_array_api.py:314 in wrapped_func
    _check_device_cpu(kwargs.pop("device", None))
  File ~/code/scikit-learn/sklearn/utils/_array_api.py:308 in _check_device_cpu
    raise ValueError(f"Unsupported device for NumPy: {device!r}")
ValueError: Unsupported device for NumPy: device(type='cpu')
```

so this is indeed a regression: when array API dispatch is disabled, the usual implicit conversion from torch CPU tensors to NumPy arrays should still happen and for some reason, we get a non-None device where we don't expect it. I need to investigate.

Labels: Bug, Regression, Array API