Query all categories once and get individual categories from array
Your issue is that as soon as you call .find(), your ElementCriteriaModel returns an array of elements. In other words, the ElementCriteriaModel is gone, and it's no longer possible to add parameters (i.e. id()) or call other methods that you'd otherwise be able to call on that object (i.e. .first()).

On the other hand – like you say in your description; if you don't use .find() (keeping the ElementCriteriaModel around) you'll hit the database every time you use the .id() method.

A workaround could be to loop over the categories and add them to an indexed array (using the category IDs as keys) and then pull your individual categories from that index instead of the original array.

Important: One gotcha to note is that the |merge filter will actually renumber numeric keys, so you have to add an arbitrary character to the ID to retain the actual ID values (the example below uses an underscore prefix):

{# Get the categories #}
{% set categories = craft.categories.group('products').limit(null).find() %}

{# Create category index #}
{% set categoryIndex = {} %}
{% for category in categories %}
    {% set categoryIndex = categoryIndex|merge({('_'~category.id): category}) %}
{% endfor %}

{# Do your thing #}
&lt;h1&gt;&lt;a href="{{ categoryIndex['_102'].url }}"&gt;{{ categoryIndex['_102'].title|raw }}&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;{{ categoryIndex['_126'].title|raw }}&lt;/h2&gt;


Note that when you want to pull a category from the index, categoryIndex['_102'] and categoryIndex._102 will both work – I just find that the former looks a bit cleaner, with the underscore in front of it (obviously you can use any character, it doesn't have to be an underscore).

Edit

As pointed out by @carlcs in the comments below, another approach to creating the index is to use the group filter. With this approach you'll avoid the underscore hack and the for loop. The gotcha here is that this filter will actually create an array of arrays, meaning you'll have to use categoryIndex[102][0] (note the [0] at the end) to access a specific category (you could also use categoryIndex[102]|first, of course):

{% set categories = craft.categories.group('products').limit(null).find() %}
{% set categoryIndex = categories|group('id') %}

&lt;h1&gt;&lt;a href="{{ categoryIndex[102][0].url }}"&gt;{{ categoryIndex[102][0].title|raw }}&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;{{ categoryIndex[126][0].title|raw }}&lt;/h2&gt;