Use `tf.Unpack` when unrolling `tf.BatchMatMul`
Please also update the test in https://github.com/tensorflow/tensorflow/blob/88e5914db537d91e779b6e6a56c593146c441bc3/tensorflow/compiler/mlir/lite/tests/end2end/unroll_batch_matmul.pbtxt

thanks. @sirakiin thanks for taking a look. I updated the mentioned test and rebased the PR onto the latest master. Hi @sirakiin Could you have a look at this PR? Thank you! Hi @sirakiin Could you have a look at this PR? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you! > Hi @lgeiger Can you please resolve conflicts? Thank you!

rebased Hi @haozha111 Can you please review this PR ? Thank you! > Hi @haozha111 Can you please review this PR ? Thank you!

Deferring to Luke who is working on TFL converter. Hi @LukeBoyer Can you please review this PR ? Thank you! Hi @LukeBoyer Can you please review this PR ? Thank you! Hi @LukeBoyer Can you please review this PR ? Thank you! Hi @LukeBoyer Can you please review this PR ? Thank you! Hi @LukeBoyer Can you please review this PR ? Thank you! Hi @LukeBoyer Can you please review this PR ? Thank you! Hi @LukeBoyer Can you please review this PR ? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you! Hi @lgeiger Can you please resolve conflicts? Thank you!


This changes the unrolling of `tf.BatchMatMul` in the TFLite converter to use a `tf.Unpack` operation instead of a `tf.Split` operation followed by multiple `tf.Reshape` operations which simplifies the resulting graph.

The difference can be observed with the following code:
```python
import tensorflow as tf

query = tf.keras.Input(shape=(15, 64), name="query", batch_size=1)
key = tf.keras.Input(shape=(15, 64), name="key", batch_size=1)
value = tf.keras.Input(shape=(15, 64), name="value", batch_size=1)

attention_layer = tf.keras.layers.MultiHeadAttention(num_heads=8, key_dim=8)

model = tf.keras.Model(
    [query, key, value], attention_layer(query=query, key=key, value=value)
)

model.save("saved_model")

converter = tf.lite.TFLiteConverter.from_saved_model("saved_model")
converter.unfold_batchmatmul = True
converter.optimizations = [tf.lite.Optimize.DEFAULT]
flatbuffer = converter.convert()

open("saved_model_unfolded.tflite", "wb").write(flatbuffer)
```
Previously this would produce the following graph which includes quite a lot of unnecessary reshape ops:
<img width="850" alt="Screenshot 2023-08-08 at 16 13 12" src="https://github.com/tensorflow/tensorflow/assets/13285808/e10cd9b1-5d1b-47e7-a2fe-ea4df784eb33">

With this change the resulting graph doesn't include these reshape ops:
<img width="746" alt="Screenshot 2023-08-08 at 17 21 16" src="https://github.com/tensorflow/tensorflow/assets/13285808/f89614e2-0e5d-4e92-b72b-a7a1fed5a87d">
