[TFLite] Support for fully quantized fused custom operators
Hi @Tessil Can you please resolve conflicts? Thank you! Hi @Tessil Can you please resolve conflicts? Thank you! @gbaned Done, thanks Hi @yijie-yang Can you please review this PR ? Thank you!
Hi,

This PR adds support for fully quantized fused custom ops with two commits:
* The first one adds a `_tfl_no_side_effect` trait to mark a function as having no side-effect so that the dangling outputs are correctly pruned. This can also be done through the `tfl-post-quantize` pass with `enable-no-side-effect=custom_op_name=true`, the commit provides a way to do it directly from the Python API.
* The second one propagate the `_tfl_quant_trait` and `_tfl_no_side_effect` traits on a custom op as operator attribute instead of as a custom option of the custom operator.

We can then annotate a function as follow to have a fully quantizated fused op:
```python
def get_implements_signature():
    implements_signature = [
        'name: "tan"',
        'attr {key: "tfl_fusable_op" value { b: true } }',
        'attr {key: "_tfl_quant_trait" value { s: "fully_quantizable" } }',
        'attr {key: "_tfl_no_side_effect" value { b: true } }',
    ]
    return " ".join(implements_signature)


@tf.function(experimental_implements=get_implements_signature())
def tan_f(x):
    return tf.math.sin(x) / tf.math.cos(x)
```