Repository: bentoml/BentoML

Issue:
bug: Run prediction fail when there is more than one output on Tensorflow/Keras
### Describe the bug

I found and bug for a multioutputs models but also have a possible solution. I have a model defined on this way:
```python
p5 = layers.Conv2D(
        ...
)(x)
return tf.keras.Model(inputs, [p5, p4, p3])
```
For personal reasons and time reasons this definition of the modal can't change.

The problems is that when the model is loaded and a predition is recieved by API, the service fail on this line:
```python
boxes, scores, labels = model.run(images_arr)
```
Whit this error:
```
File "c:\users\emman\appdata\local\programs\python\python39\lib\site-packages\anyio\_backends\_asyncio.py", line 867, in run
    result = context.run(func, *args)
  File "G:\Research\BiometricYOLOv5-DH\application\src\create_service.py", line 346, in predict
    raise e
  File "G:\Research\BiometricYOLOv5-DH\application\src\create_service.py", line 344, in predict
    boxes, scores, labels = predictor(model.run(images_np))
  File "c:\users\emman\appdata\local\programs\python\python39\lib\site-packages\bentoml\_internal\runner\runner.py", line 52, in run
    return self.runner._runner_handle.run_method(self, *args, **kwargs)
  File "c:\users\emman\appdata\local\programs\python\python39\lib\site-packages\bentoml\_internal\runner\runner_handle\local.py", line 48, in run_method
    return getattr(self._runnable, __bentoml_method.name)(*args, **kwargs)
  File "c:\users\emman\appdata\local\programs\python\python39\lib\site-packages\bentoml\_internal\runner\runnable.py", line 139, in method
    return self.func(obj, *args, **kwargs)  File "c:\users\emman\appdata\local\programs\python\python39\lib\site-packages\bentoml\_internal\frameworks\tensorflow_v2.py", line 338, in run_method
    return _run_method(runnable_self, *args, **kwargs)
  File "c:\users\emman\appdata\local\programs\python\python39\lib\site-packages\bentoml\_internal\frameworks\tensorflow_v2.py", line 323, in _run_method
    return _postprocess(res)
  File "c:\users\emman\appdata\local\programs\python\python39\lib\site-packages\bentoml\_internal\frameworks\tensorflow_v2.py", line 289, in _postprocess
    return t.cast("ext.NpNDArray", res.numpy())
AttributeError: 'list' object has no attribute 'numpy'
```
This is because the outputs is a `list`, I saw your source code and found this:
```python
else:
    # if there are no output signature or more than one output
    # signatures, the post process function need to do casting
    # depends on the real output value each time

    def _postprocess(res: TFModelOutputType) -> TFRunnableOutputType:
        if isinstance(res, tuple):
            return tuple(t.cast("ext.NpNDArray", r.numpy()) for r in res)
        else:
            return t.cast("ext.NpNDArray", res.numpy())
```
Normally, expect that the output is a tuple to execute `numpy` function to each element and when not execute directly, but in these case fail.

I guess that a solution could be that is the `res` instance is a list or tuple just execute `numpy`function or add new condition just for `list`. **I tested that on my proyect and works succesfully**, here is a PR #3807 
This first solution:
```python
def _postprocess(res: TFModelOutputType) -> TFRunnableOutputType:
    if isinstance(res, tuple) or isinstance(res, list):
        type_collection = tuple if isinstance(res, tuple) else list
        return type_collection(t.cast("ext.NpNDArray", r.numpy()) for r in res)
    else:
        return t.cast("ext.NpNDArray", res.numpy())
```

The second solution:   
```python
def _postprocess(res: TFModelOutputType) -> TFRunnableOutputType:
    if isinstance(res, tuple):
        return tuple(t.cast("ext.NpNDArray", r.numpy()) for r in res)
    elif isinstance(res, list):
        return [t.cast("ext.NpNDArray", r.numpy()) for r in res]
    else:
        return t.cast("ext.NpNDArray", res.numpy())
```            

### To reproduce

_No response_

### Expected behavior

_No response_

### Environment

bentoml 1.0.18
python 3.9.0
windows 11


Discussion:

Resolving patch:
diff --git a/src/bentoml/_internal/frameworks/tensorflow_v2.py b/src/bentoml/_internal/frameworks/tensorflow_v2.py
--- a/src/bentoml/_internal/frameworks/tensorflow_v2.py
+++ b/src/bentoml/_internal/frameworks/tensorflow_v2.py
@@ -283,7 +283,7 @@ def _postprocess(res: tf_ext.EagerTensor) -> TFRunnableOutputType:
             # depends on the real output value each time
 
             def _postprocess(res: TFModelOutputType) -> TFRunnableOutputType:
-                if isinstance(res, tuple):
+                if isinstance(res, (tuple, list)):
                     return tuple(t.cast("ext.NpNDArray", r.numpy()) for r in res)
                 else:
                     return t.cast("ext.NpNDArray", res.numpy())


Test patch: