Make WPF Image load async

I suggest you to use a Binding on your imgGravatar from XAML. Set IsAsync=true on it and WPF will automatically utilize a thread from the thread pool to pull your image. You could encapsulate the resolving logic into an IValueConverter and simply bind the email as Source

in XAML:

<Window.Resouces>
    <local:ImgConverter x:Key="imgConverter" />
</Window.Resource>

...


<Image x:Name="imgGravatar" 
       Source="{Binding Path=Email, 
                        Converter={StaticResource imgConverter}, 
                        IsAsync=true}" />

in Code:

public class ImgConverter : IValueConverter
{
    public override object Convert(object value, ...)
    {
        if (value != null)
        {
             BitmapImage bi = new BitmapImage();
             bi.BeginInit();
             bi.UriSource = new Uri( 
                 GravatarImage.GetURL(
                     "http://www.gravatar.com/avatar.php?gravatar_id=" + 
                      value.ToString()) , UriKind.Absolute 
                 );
             bi.EndInit();
             return bi;                
        }
        else
        {
            return null;
        }

    }
}

I can't see why your code would block the UI, as BitmapImage supports downloading image data in the background. That's why it has an IsDownloading property and a DownloadCompleted event.

Anyway, the following code shows a straightforward way to download and create the image entirely in a separate thread (from the ThreadPool). It uses a WebClient instance to download the whole image buffer, before creating a BitmapImage from that buffer. After the BitmapImage is created it calls Freeze to make it accessible from the UI thread. Finally it assigns the Image control's Source property in the UI thread by means of a Dispatcher.BeginInvoke call.

ThreadPool.QueueUserWorkItem(
    o =>
    {
        var url = GravatarImage.GetURL(
           "http://www.gravatar.com/avatar.php?gravatar_id=" + email);
        var webClient = new WebClient();
        var buffer = webClient.DownloadData(url);
        var bitmapImage = new BitmapImage();

        using (var stream = new MemoryStream(buffer))
        {
            bitmapImage.BeginInit();
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.StreamSource = stream;
            bitmapImage.EndInit();
            bitmapImage.Freeze();
        }

        Dispatcher.BeginInvoke((Action)(() => image.Source = bitmapImage));
    });

EDIT: today you would just use async methods:

var url = GravatarImage.GetURL(
    "http://www.gravatar.com/avatar.php?gravatar_id=" + email);
var httpClient = new HttpClient();
var responseStream = await httpClient.GetStreamAsync(url);
var bitmapImage = new BitmapImage();

using (var memoryStream = new MemoryStream())
{
    await responseStream.CopyToAsync(memoryStream);

    bitmapImage.BeginInit();
    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
    bitmapImage.StreamSource = memoryStream;
    bitmapImage.EndInit();
    bitmapImage.Freeze();
}

image.Source = bitmapImage;