**Description**

Currently `BaseOperator` and `XComArgs` implements the same logic of `__lshift__`, `__rshift__` and others "chain" operations (`>>`, `<<`). It seems resonable to abstract this logic into `TaskMixin` to introduce some DRYness especially because the new concept of `TaskGroup` will also implement the same methods.

**Use case / motivation**

Limit duplication of logic.

**Related Issues**

https://github.com/apache/airflow/pull/10827#issuecomment-691927501
#10153 

airflow/models/baseoperator.py
self, content: Any, context: Dict, jinja_env: jinja2.Environment, seen_oids: Set
    ) -> None:
        if id(content) not in seen_oids:
            seen_oids.add(id(content))
            try:
                nested_template_fields = content.template_fields
            except AttributeError:
                
                return
            self._do_render_template_fields(content, nested_template_fields, context, jinja_env, seen_oids)
    def get_template_env(self) -> jinja2.Environment:
        """Fetch a Jinja template environment from the DAG or instantiate empty environment if no DAG."""
        return self.dag.get_template_env() if self.has_dag() else jinja2.Environment(cache_size=0)  
    def prepare_template(self) -> None:
        """
        Hook that is triggered after the templated fields get replaced
        by their content. If you need your operator to alter the
        content of the file before the template is rendered,
        it should override this method to do so.
        """
    def resolve_template_files(self) -> None: